import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
@SuppressWarnings("serial")
public class BoardGui extends Applet {
	
	public static final int PIECE_SIZE = 20;
	public static final int BORDER = 20;
	public static final int BOARD_WIDTH = 222;
	public static final int HEIGHT = 422;
	public static final Dimension SCORE = new Dimension(120,60);
	public static final Dimension NEXT = new Dimension(120,120);
	public static final int LEVEL_WIDTH = 100;

	private static final int ROUND = 2;

	
	private ArrayList<Image> images;
	private Board my_board;
	private Timer t;
	
	public BoardGui() {
		t = new Timer(1000,new TetrisListener());
		t.start();
		images = new ArrayList<Image>();
		loadImages();
		my_board = new Board();
		addKeyListener(new TetrisKeyListener());
		setFocusable(true);
	}


	private Color getColor(int id) {
		Color c;
		switch (id) {
		case Piece.I_ID:
			c = Color.BLUE;
			break;
		case Piece.J_ID:
			c = Color.GREEN;
			break;
		case Piece.L_ID:
			c = Color.MAGENTA;
			break;
		case Piece.O_ID:
			c = Color.ORANGE;
			break;
		case Piece.S_ID:
			c = Color.RED;
			break;
		case Piece.T_ID:
			c = Color.YELLOW;
			break;
		case Piece.Z_ID:
			c = Color.WHITE;
			break;
		default:
			c = Color.GRAY;
			break;
		}
		return c;
	}

	private Dimension getCenter(Block b) {
		int id = b.getId();
		if (id == Piece.I_ID) {
			return new Dimension(50, 20);
		} else if (id == Piece.J_ID | id == Piece.L_ID) {
			return new Dimension(40, 30);
		} else if (id == Piece.S_ID | id == Piece.Z_ID | id == Piece.T_ID) {
			return new Dimension(30, 40);
		} else {
			return new Dimension(40, 40);
		}
	}

	private void drawNumber(int number, Graphics g, int y,int x) {
		int next = 0;
		int rest = number;
		int width = x;
		Image i;
		while(rest >= 10){
			next = rest%10;
			i = images.get(next);
			rest = rest/10;
			width = width-(i.getWidth(this)/4);
			g.drawImage(i, width, y,i.getWidth(this)/4,i.getHeight(this)/4, this);
		}

		i = images.get(rest);
		width = width-(i.getWidth(this)/4);
		g.drawImage(images.get(rest),width,y, i.getWidth(this)/4, i.getHeight(this)/4, this);
	}

	private void loadImages() {
		Image im;
		for (int i = 0; i <= 9; i++) {
			try {
				im = ImageIO.read(getClass().getResourceAsStream("/"+i+".png"));
				images.add(im);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	
		try {
			im = ImageIO.read(getClass().getResourceAsStream("/next.png"));
			images.add(im);
			im = ImageIO.read(getClass().getResourceAsStream("/score.png"));
			images.add(im);
			im = ImageIO.read(getClass().getResourceAsStream("/level.png"));
			images.add(im);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	public void moveDown(){
		my_board.moveDown();
	}
	
	public void moveLeft(){
		my_board.moveLeft();
	}
	
	public void moveRight(){
		my_board.moveRight();
	}
	
	public void rotate(){
		my_board.rotate();
	}
	public int getSpeed(){
		return 1000-((my_board.getLevel()-1)*100);
	}
	public boolean gameOver(){
		return my_board.gameOver();
	}
	@Override
	public void paint(Graphics g) {
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setColor(Color.RED);
		
		// drawing game board
		int height = images.get(10).getHeight(this)/8;
		g.drawRoundRect(0, height, BOARD_WIDTH, HEIGHT, ROUND, ROUND);
		for(Block b : my_board.getBlocks()){
			g.setColor(this.getColor(b.getId()));
			g.drawRoundRect(b.getX()*PIECE_SIZE+1, b.getY()*PIECE_SIZE+1+height, PIECE_SIZE-1, PIECE_SIZE-1,ROUND, ROUND);
		}
		for(Block b : my_board.getCurentPiece().getPiece()){
			g.setColor(this.getColor(b.getId()));
			g.drawRoundRect(b.getX()*PIECE_SIZE+1, b.getY()*PIECE_SIZE+1+height, PIECE_SIZE-1, PIECE_SIZE-1,ROUND, ROUND);
		}
		
		//drawing next Piece Panel
		height = 0;
		int width = BOARD_WIDTH+BORDER;
		Image i = images.get(10);
		g.drawImage(i, width, height,i.getWidth(this)/4,i.getHeight(this)/4, this);
		height = i.getHeight(this)/4;
		g.setColor(Color.YELLOW);
		g.drawRoundRect(width, height, NEXT.width,NEXT.height , ROUND, ROUND);
		Dimension center;
		int x;
		int y;
		for(Block b : my_board.getNextPiece().getPiece()){
			center = this.getCenter(b);
			x = (b.getX()-my_board.getNextPiece().getX())*PIECE_SIZE+1 + width+center.width;
			y = b.getY()*PIECE_SIZE+1+height+center.height;
			g.setColor(this.getColor(b.getId()));
			g.drawRoundRect(x, y, PIECE_SIZE-1, PIECE_SIZE-1,ROUND, ROUND);
		}
		
		// drawing score Panel
		height = height+NEXT.height+BORDER;
		i = images.get(11);
		g.drawImage(i, width, height,i.getWidth(this)/4,i.getHeight(this)/4, this);
		height = i.getHeight(this)/4+height;
		g.setColor(Color.BLUE);
		g.drawRoundRect(width, height, SCORE.width,SCORE.height , ROUND, ROUND);
		this.drawNumber(my_board.getScore(), g, height+10,width+SCORE.width);
		
		// drawing level Panel
		height = height+SCORE.height+BORDER;
		i = images.get(12);
		g.drawImage(i, width, height,i.getWidth(this)/4,i.getHeight(this)/4, this);
		height = i.getHeight(this)/4+height;
		g.setColor(Color.MAGENTA);
		g.drawRoundRect(width, height, SCORE.width,SCORE.height , ROUND, ROUND);
		this.drawNumber(my_board.getLevel(), g, height+10,width+SCORE.width);
	}
	public void init() {
		// Execute a job on the event-dispatching thread; creating this applet's
		// GUI.
		try {
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					setVisible(true);
					setFocusable(true);
				}
			});
		} catch (Exception e) {
			System.err.println("createGUI didn't complete successfully");
		}
	}
	public class TetrisKeyListener implements KeyListener {
		private void getAction(KeyEvent arg0) {
			if (arg0.getKeyCode() == KeyEvent.VK_DOWN) {
				my_board.moveDown();
				repaint();
			} else if (arg0.getKeyCode() == KeyEvent.VK_LEFT) {
				my_board.moveLeft();
				repaint();
			} else if (arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
				my_board.moveRight();
				repaint();
			} else if (arg0.getKeyCode() == KeyEvent.VK_UP) {
				my_board.rotate();
				repaint();

			}
		}

		@Override
		public void keyPressed(KeyEvent arg0) {
			getAction(arg0);
		}

		@Override
		public void keyReleased(KeyEvent arg0) {
		}

		@Override
		public void keyTyped(KeyEvent arg0) {

		}

	}

	class TetrisListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			my_board.moveDown();
			repaint();
			if(!my_board.gameOver()){
				t.setDelay(getSpeed());	
			}else{
				t.stop();
			}
		}

	}
}
